package cn.dengta.webapp.trade.dao;

import java.util.List;

import cn.dengta.common.model.TimeInterval;
import cn.dengta.common.web.Page;
import cn.dengta.webapp.base.dao.BaseDao;
import cn.dengta.webapp.base.util.MybatisUtil;
import cn.dengta.webapp.trade.dto.UserCoinLogSumDTO;
import cn.dengta.webapp.trade.dto.UserCoinSumDTO;
import cn.dengta.webapp.trade.entity.UserCoinLog;
import cn.dengta.webapp.trade.form.UserCoinLogQuery;
import cn.dengta.webapp.trade.model.*;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.enums.SqlKeyword;
import me.codeplayer.util.StringUtil;
import org.apache.ibatis.annotations.*;
import org.apache.ibatis.jdbc.SQL;

import static cn.dengta.webapp.trade.entity.UserCoinLog.ADD_TIME;
import static cn.dengta.webapp.trade.entity.UserCoinLog.FLOW;
import static cn.dengta.webapp.trade.entity.UserCoinLog.HANDLE_STATUS;
import static cn.dengta.webapp.trade.entity.UserCoinLog.ID;
import static cn.dengta.webapp.trade.entity.UserCoinLog.TO_USER_ID;
import static cn.dengta.webapp.trade.entity.UserCoinLog.TRADE_TYPE;
import static cn.dengta.webapp.trade.entity.UserCoinLog.USER_ID;
import static cn.dengta.webapp.trade.entity.UserIntegralLog.*;

/**
 * 钻石流水记录表 Mapper 接口
 */
public interface UserCoinLogDao extends BaseDao<UserCoinLog> {

	/**
	 * 查询指定用户、指定交易时间段、指定交易类型(可变参数)的交易数据键/值对(交易类型/交易金额)即可
	 */
	@SelectProvider(type = UserCoinLogSQL.class, method = "getSumOfTradeAmountGroupByType")
	List<UserCoinLogSumDTO> getSumOfTradeAmountGroupByType(@Param("userIds") Long[] userIds, @Param("toUserIds") Long[] toUserIds, @Param("flow") Integer flow, @Param("interval") TimeInterval addTimeInterval, @Param("tradeTypes") TradeType... tradeTypes);

	@Select("SELECT * FROM tr_user_coin_log log JOIN dt_user u ON u.id = log.user_id ${ew.customSqlSegment} ")
	Page<UserCoinLog> findPage(Page<UserCoinLog> page, @Param("ew") QueryWrapper<UserCoinLog> wrapper);

	@Update("UPDATE tr_user_coin_log SET handle_status = 9, update_time = NOW() WHERE id = #{id} AND handle_status = 0")
	int updateHandleStatus(@Param("id") Long id);

	/**
	 * 查询指定用户、指定交易时间段、指定交易类型(可变参数)的交易数据
	 */
	@SelectProvider(type = UserCoinLogSQL.class, method = "findSumOfInfo")
	List<UserCoinLogSumDTO> findSumOfInfo(@Param("query") UserCoinLogQuery query, @Param("interval") TimeInterval addTimeInterval, @Param("tradeTypes") TradeType... tradeTypes);

	@SelectProvider(type = UserCoinLogSQL.class, method = "getSumOfTodayCoin")
	UserCoinLogSumDTO getSumOfTodayCoin(@Param("userId") Long userId, @Param("toUserId") Long toUserId, @Param("interval") TimeInterval timeInterval, @Param("tradeType") TradeType tradeType);

	@SelectProvider(type = UserCoinLogSQL.class, method = "getSumOfYesterdayCoin")
	UserCoinLogSumDTO getSumOfYesterdayCoin(@Param("userId") Long userIds, @Param("interval") TimeInterval timeInterval);


	@Select("SELECT " +
			"user_id," +
			"to_user_id," +
			"ABS(SUM(trade_amount)) totalCoin," +
			"SUM(IF(trade_type='COIN_FOR_GIFT',ABS(trade_amount),0))  giftCoin," +
			"SUM(IF(trade_type IN ('COIN_FOR_GREET','COIN_FOR_MSG'),ABS(trade_amount),0))  msgCoin," +
			"SUM(IF(trade_type IN ('COIN_FOR_AUDIO','COIN_FOR_AI_SPEED'),ABS(trade_amount),0)) audioCoin," +
			"SUM(IF(trade_type IN ('COIN_FOR_VIDEO'),ABS(trade_amount),0)) videoCoin " +
			"FROM tr_user_coin_log " +
			"WHERE user_id = #{userId} " +
			"AND trade_type IN ('COIN_FOR_GIFT','COIN_FOR_GREET','COIN_FOR_MSG','COIN_FOR_AUDIO','COIN_FOR_AI_SPEED','COIN_FOR_VIDEO') " +
			"AND flow = -1 GROUP BY to_user_id")
	List<UserCoinSumDTO> coinDetailExport(@Param("userId") Long userId);

	class UserCoinLogSQL {

		public String getSumOfTradeAmountGroupByType(@Param("userIds") Long[] userIds, @Param("toUserIds") Long[] toUserIds, @Param("flow") Integer flow, @Param("interval") TimeInterval addTimeInterval, @Param("tradeTypes") TradeType... tradeTypes) {
			SQL sql = new SQL().SELECT("user_id userId, trade_type tradeType, IFNULL(SUM(trade_amount),0) totalTradeAmount").FROM("tr_user_coin_log");
			MybatisUtil.appendEqSql(sql, FLOW, flow, "#{flow}");
			MybatisUtil.appendInIdSql(sql, USER_ID, userIds);
			MybatisUtil.appendInIdSql(sql, TO_USER_ID, toUserIds);
			MybatisUtil.appendInStrSql(sql, TRADE_TYPE, tradeTypes);
			MybatisUtil.appendSql(sql, HANDLE_STATUS, SqlKeyword.GE, HandleStatus.INIT.getValue(), HandleStatus.INIT.getValue().toString());
			MybatisUtil.appendSqlInterval(sql, ADD_TIME, addTimeInterval, null);
			sql.GROUP_BY(TRADE_TYPE);
			return sql.toString();
		}

		public String findSumOfInfo(@Param("query") UserCoinLogQuery query, @Param("interval") TimeInterval addTimeInterval, @Param("tradeTypes") TradeType... tradeTypes) {
			final String prefix = "log.";
			StringBuilder sb = new StringBuilder(600)
					.append("log.user_id userId," +
							" log.trade_type tradeType," +
							" COUNT(DISTINCT(log.user_id)) userCount," +
							" ABS(IFNULL(SUM(log.trade_amount),0)) totalTradeAmount," +
							" ABS(IFNULL(SUM(log.trade_free_part),0)) totalFreeTradeAmount," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_ACTIVITY', log.trade_amount, 0))) activityCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_DONATE', log.trade_amount, 0))) donateCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_GAME', log.trade_amount, 0))) gameCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_EXCHANGE_GOLD', log.trade_amount, 0))) exchangeGoldCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_GIFT_GOLD', log.trade_amount, 0))) giftGoldCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_GREET', log.trade_amount, 0))) greetCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_MSG', log.trade_amount, 0))) msgCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_AUDIO', log.trade_amount, 0))) audioCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_VIDEO', log.trade_amount, 0))) videoCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_GIFT', log.trade_amount, 0))) giftCoin," +
							" ABS(SUM(IF(log.trade_type = 'COIN_FOR_GIFT_LIVE', log.trade_amount, 0))) giftLiveCoin");
			SQL sql = new SQL()
					.SELECT(sb.append(StringUtil.toString(query.selectKey)).toString())
					.FROM("tr_user_coin_log log");
			MybatisUtil.appendEqSql(sql, prefix + FLOW, query.getFlow(), "#{query.flow}");
			MybatisUtil.appendInStrSql(sql, prefix + TRADE_TYPE, tradeTypes);
			MybatisUtil.appendInIdSql(sql, prefix + USER_ID, query.getUserIds());
			MybatisUtil.appendSql(sql, prefix + HANDLE_STATUS, SqlKeyword.GE, HandleStatus.INIT.getValue(), HandleStatus.INIT.getValue().toString());
			MybatisUtil.appendSqlInterval(sql, prefix + ADD_TIME, addTimeInterval, null);
			sql.GROUP_BY(StringUtil.notEmpty(query.groupAttr) ? query.groupAttr : prefix + USER_ID);
			sql.ORDER_BY(prefix + ID);
			return sql.toString();
		}

		public String getSumOfTodayCoin(@Param("userId") Long userId, @Param("toUserId") Long toUserId, @Param("interval") TimeInterval timeInterval, @Param("tradeType") TradeType tradeType) {
			SQL sql = new SQL().SELECT("user_id userId, trade_type tradeType, IFNULL(ABS(SUM(trade_amount)),0) totalTradeAmount").FROM("tr_user_coin_log");
			MybatisUtil.appendEqSql(sql, USER_ID, userId, "#{userId}");
			MybatisUtil.appendEqSql(sql, TO_USER_ID, toUserId, "#{toUserId}");
			MybatisUtil.appendEqSql(sql, FLOW, Flow.CONSUME.value, "'-1'");
			MybatisUtil.appendEqSql(sql, TRADE_TYPE, tradeType, "#{tradeType.name}");
			MybatisUtil.appendSql(sql, HANDLE_STATUS, SqlKeyword.GE, HandleStatus.INIT.getValue(), HandleStatus.INIT.getValue().toString());
			MybatisUtil.appendSqlInterval(sql, ADD_TIME, timeInterval, null);
			return sql.toString();
		}

		public String getSumOfYesterdayCoin(@Param("userId") Long userId, @Param("interval") TimeInterval interval) {
			SQL sql = new SQL().SELECT("user_id userId, IFNULL(ABS(SUM(trade_amount)),0) totalTradeAmount").FROM("tr_user_coin_log");
			MybatisUtil.appendEqSql(sql, FLOW, "-1", "-1");
			MybatisUtil.appendEqSql(sql, USER_ID, userId, "#{userId}");
			MybatisUtil.appendSql(sql, HANDLE_STATUS, SqlKeyword.GE, HandleStatus.INIT.getValue(), HandleStatus.INIT.getValue().toString());
			MybatisUtil.appendSqlInterval(sql, ADD_TIME, interval, null);
			return sql.toString();
		}

	}

}
